Introduction aux Streams
Un Stream est un pipeline de traitement sur une séquence d'éléments. Il ne stocke pas de données — il décrit comment les transformer, de la source jusqu'au résultat.
Les Streams sont omniprésents avec les références de méthodes (Cours 05) et produisent souvent des Optional (Cours 05). Le détail complet des opérations est couvert au Cours 06.
Créer un Stream
// À partir d'une collection
List<String> noms = List.of("Alice", "Bob", "Clara");
Stream<String> s1 = noms.stream();
// À partir de valeurs directes
Stream<String> s2 = Stream.of("Alice", "Bob", "Clara");
// À partir d'un tableau
String[] tab = {"Alice", "Bob", "Clara"};
Stream<String> s3 = Arrays.stream(tab);
// Plage d'entiers (IntStream)
IntStream nombres = IntStream.range(1, 6); // 1, 2, 3, 4, 5
IntStream inclus = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5
Pattern de base
Un Stream se compose toujours de trois parties :
source.stream() // 1. Création
.operation(...) // 2. Opération(s) intermédiaire(s) — transforme
.operationTerminale(); // 3. Opération terminale — déclenche et consomme
Exemple concret :
List<String> noms = List.of("Alice", "Bob", "Alexandre");
List<String> resultat = noms.stream()
.filter(n -> n.startsWith("A")) // intermédiaire
.map(String::toUpperCase) // intermédiaire
.collect(Collectors.toList()); // terminale
// resultat → [ALICE, ALEXANDRE]
Un Stream ne peut être consommé qu'une seule fois. Après l'opération terminale, il est épuisé.
Deux caractéristiques importantes
Paresseux (lazy) : les opérations intermédiaires ne s'exécutent pas tant qu'aucune opération terminale n'est appelée.
Non modifiant : un Stream ne modifie jamais la collection source — il produit un nouveau résultat.
Pour les opérations intermédiaires (filter, map, sorted) et terminales (collect, reduce, count) seront vus au prochain cours.